﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;


namespace ZCConsole.VOBC
{
    class NonCommunicationTrain
    {
        public static Dictionary<UInt16, TrainInfo> LoseTrain = new Dictionary<UInt16, TrainInfo>();
        Timer CheckNonCommunicateTrain;
        private HandleVobc handleVobc;
        private ZC zc;
        private UpdateRoute updateRoute;
        private UpdateTrainPosition updateTrain;

        public NonCommunicationTrain(HandleVobc handleVobc, ZC zc, UpdateRoute updateRoute, UpdateTrainPosition updateTrain)
        {
            this.updateTrain = updateTrain;
            this.updateRoute = updateRoute;
            this.zc = zc;
            this.handleVobc = handleVobc;
            CheckNonCommunicateTrain = new Timer(new TimerCallback(JudgeLostTrain), null, 2000, 2000);
        }


        public void JudgeLostTrain(object o)
        {
            lock (handleVobc.VOBCNonCom)
            {
                Judge(handleVobc.VOBCNonCom);
                handleVobc.VOBCNonCom.Clear();
            }
            UpdateLostTrain(zc);
            UpdateAccessOfTrain();
        }

        private void Judge(List<UInt16> VOBCList)
        {
            lock (updateTrain.PreTrainPosition)
            {
                foreach (var item in updateTrain.PreTrainPosition.Keys)
                {
                    if (!VOBCList.Contains(item))
                    {
                        if (!LoseTrain.Keys.Contains(item))
                        {

                            LoseTrain.Add(item, updateTrain.PreTrainPosition[item]);
                        }
                    }
                }
            }
        }

        private void UpdateLostTrain(ZC zc)
        {
            foreach (var trainID in LoseTrain.Keys)
            {
                HandlePosition(trainID, LoseTrain[trainID].HeadPosition, zc);
                HandlePosition(trainID, LoseTrain[trainID].TailPosition, zc);
            }
        }

        private void HandlePosition(ushort trainID, Device device, ZC zc)
        {
            if (device is Section)
            {
                (device as Section).SetNonCommunicateTrain(trainID, true);
            }
            else if (device is RailSwitch)
            {
                RailSwitch railswitch = device as RailSwitch;
                railswitch.SetNonCommunicateTrain(trainID, true);

                RailSwitch railNeedToChange = FindAnotherRailswitch(railswitch, zc);
                if (railNeedToChange != null)
                {
                    railNeedToChange.SetNonCommunicateTrain(trainID, true);

                }
            }
        }

        private RailSwitch FindAnotherRailswitch(RailSwitch railswitch, ZC zc)
        {
            RailSwitch railNeedToChange = zc.data.Devices.Find((Device element) =>
            {
                if (element is RailSwitch)
                {
                    if ((element as RailSwitch).section.Name == railswitch.section.Name && (element as RailSwitch).Name != railswitch.Name)
                    {
                        return true;
                    }
                }
                return false;
            }) as RailSwitch;
            return railNeedToChange;
        }

        private void UpdateAccessOfTrain()
        {
            foreach (var trainID in LoseTrain.Keys)
            {
                lock (updateRoute.PreAccess)
                {
                    if (updateRoute.PreAccess.Keys.Contains(trainID))
                    {
                        foreach (var device in updateRoute.PreAccess[trainID])
                        {
                            if (device is Section)
                            {
                                Section section = device as Section;
                                section.SetRouteOpen(trainID, false, LogicSection.Left);
                                section.SetRouteOpen(trainID, false, LogicSection.Right);
                            }
                            else if (device is RailSwitch)
                            {
                                (device as RailSwitch).SetRouteOpen(trainID, false);
                            }

                        }
                        updateRoute.PreAccess.Remove(trainID);
                    }
                }
            }
        }


    }
}
